/*
 *      filter.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#ifndef _FILTER_IMPL
#define _FILTER_IMPL

#include "filter.h"

#define ITEM_ID item->children->PROPERTIES
/**\brief Inserisce i nodi marcati come positivi dai filtri nella lista di positivi
 *
 * Questa funzione riceve in input il puntatore alla lista di positivi e il puntatore al xmlNode da inserirvi ed
 * effettua un inserimento ordinato in base all'indirizzo del nodo nella lista generale AlertList.
 * \param xmlNodeList *top Puntatore alla lista di positivi
 * \param xmlNode *src Puntatore al nodo da inserire
 */
#ifdef _WIN32 
static void setNodePointer(xmlNodeList *top,AlertList *src){
#else
void setNodePointer(xmlNodeList *top,AlertList *src){
#endif
	xmlNodeList *cur,*new_el,*old;
	cur=NULL;
	new_el=NULL;
	old=NULL;
	
	if(top!=NULL){ /* la lista passata o non è vuota, o è stato appena fatto newxmlnodelist()*/
		if(top->item==NULL){ /* è stato appena fatto newxmlnodelist() */
			top->item=src;
		}else{ /* la lista non è vuota */
			/* A questo punto so che devo creare il nuovo spazio in memoria
			   perchè non sono piu il primo della lista dei positivi */
			cur=top; /* inizio dal primo della lista */
			while(cur!=NULL){ /* controllo che non sia sul next dell'ultimo */
				if(cur->item > src){ /* non è  */
					if(!(new_el=(xmlNodeList *)malloc(sizeof(xmlNodeList)))){printf("ERR - SetNodePointer: Malloc Failed %p\n",new_el);}
					new_el->item=cur->item;
					new_el->next=cur->next;
					cur->item=src;
					cur->next=new_el;
					return;
				}
				old=cur;
				cur=cur->next;
			}
			old->next=(xmlNodeList *)calloc(1,sizeof(xmlNodeList));
			old->next->item=src;
			old->next->next=NULL;
		}
	}
	return;
}

/**\brief Esegue l'operazione logica AND tra due liste di positivi
 *
 * Ricevendo come input due liste di positivi ordinate è possibile eseguire l'operazione AND tra le due in modo ottimizzato.
 * \param xmlNodeList *lista Prima lista di positivi ordinata
 * \param cmlNodeList *listb Seconda lista di positivi ordinata
 * \param strinList *sel Lista delle stringhe della parte select della query (se questa lista ha valore NULL significa che l'operatore non è a livello root nel processingTree e quindi che non deve inviare i dati in rete ma restituire la lista di positivi)
 * \param VortexConnection *cn Connessione sulla quale inviare la lista risultante (usato solo se *sel non ha valore NULL)
 * \param VortexChannell *ch Canale sul quale inviare la lista risultante (usato solo se *sel non ha valore NULL)
 * \return xmlNodeList * Lista risultante dall'esecuzione dell'operazione logica AND tra lista e listb (assume valore NULL sel sel ha valore diverso da NULL e quindi i dati vanno inviati via rete)
 */
#ifdef _WIN32 
static xmlNodeList *join(unsigned char sign_mode,int sign_num,int step_num,xmlNodeList *lista,xmlNodeList *listb,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *join(unsigned char sign_mode,int sign_num,int step_num,xmlNodeList *lista,xmlNodeList *listb,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	xmlNodeList *pos,*cura,*curb;
	int cnt=0,matched=0;
	
	/*DBG*/DEBUG == DBG_FILTERS ? print_xmlNodeList(lista) : 0;
	/*DBG*/DEBUG == DBG_FILTERS ? print_xmlNodeList(listb) : 0;
	/*DBG*/DEBUG == DBG_FILTERS ? getchar() : 0;

	cura=lista;
	curb=listb;
	pos=newxmlNodeList();
	while(cura!=NULL && curb!=NULL){
		if(cura->item>curb->item){
			curb=curb->next;
		}else if(curb->item>cura->item){
			cura=cura->next;
		}else if(cura->item==curb->item){
			/*DBG*/DEBUG == DBG_FILTERS ? matched++ : 0;
			if(sel==NULL){
				setNodePointer(pos,cura->item);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,cura->item,sel,cn,ch);
			}
			cura=cura->next;
			curb=curb->next;
		}
	}

	/*DBG*/DEBUG == DBG_FILTERS ? printf("DBG - AND->MATCHED %d\n",matched) : 0;
	freexmlNodeList(lista);
	freexmlNodeList(listb);
	return (cnt>0)? pos : freexmlNodeList(pos);
	
}



/**\brief Esegue l'operazione logica OR tra due liste di positivi
 *
 * Ricevendo come input due liste di positivi ordinate è possibile eseguire l'operazione OR tra le due in modo ottimizzato.
 * \param xmlNodeList *lista Prima lista di positivi ordinata
 * \param cmlNodeList *listb Seconda lista di positivi ordinata
 * \param strinList *sel Lista delle stringhe della parte select della query (se questa lista ha valore NULL significa che l'operatore non è a livello root nel processingTree e quindi che non deve inviare i dati in rete ma restituire la lista di positivi)
 * \param VortexConnection *cn Connessione sulla quale inviare la lista risultante (usato solo se *sel non ha valore NULL)
 * \param VortexChannell *ch Canale sul quale inviare la lista risultante (usato solo se *sel non ha valore NULL)
 * \return xmlNodeList * Lista risultante dall'esecuzione dell'operazione logica OR tra lista e listb (assume valore NULL sel sel ha valore diverso da NULL e quindi i dati vanno inviati via rete)
 */
#ifdef _WIN32 
static xmlNodeList *or(unsigned char sign_mode,int sign_num,int step_num,xmlNodeList *lista,xmlNodeList *listb,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
xmlNodeList *or(unsigned char sign_mode,int sign_num,int step_num,xmlNodeList *lista,xmlNodeList *listb,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	xmlNodeList *pos,*cura,*curb;
	int cnt=0,matched=0;
	
	/*DBG*/DEBUG == DBG_FILTERS ? printf("lista: %d\n",cnt_xmlNodeList(lista)) : 0;
	/*DBG*/DEBUG == DBG_FILTERS ? printf("listb: %d\n",cnt_xmlNodeList(listb)) : 0;
	/*DBG*/DEBUG == DBG_FILTERS ? print_xmlNodeList(lista) : 0;
	/*DBG*/DEBUG == DBG_FILTERS ? print_xmlNodeList(listb) : 0;

	cura=lista;
	curb=listb;
	pos=newxmlNodeList();
	while(cura!=NULL && curb!=NULL){
		if(cura->item>curb->item){
			/*DBG*/DEBUG == DBG_FILTERS ? matched++ : 0;
			if(sel==NULL){
				setNodePointer(pos,curb->item);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,curb->item,sel,cn,ch);
			}
			curb=curb->next;
		}else if(curb->item>cura->item){
			/*DBG*/DEBUG == DBG_FILTERS ? matched++ : 0;
			if(sel==NULL){
				setNodePointer(pos,cura->item);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,cura->item,sel,cn,ch);
			}
			cura=cura->next;
		}else if(cura->item==curb->item){
			/*DBG*/DEBUG == DBG_FILTERS ? matched++ : 0;
			if(sel==NULL){
				setNodePointer(pos,cura->item);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,cura->item,sel,cn,ch);
			}
			cura=cura->next;
			curb=curb->next;
		}
	}
	while(cura!=NULL){
		/*DBG*/DEBUG == DBG_FILTERS ? printf("DBG - A_CATCHED!\n") : 0;
		/*DBG*/DEBUG == DBG_FILTERS ? matched++ : 0;
		if(sel==NULL){
				setNodePointer(pos,cura->item);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,cura->item,sel,cn,ch);
			}
		cura=cura->next;
	}
	while(curb!=NULL){
		/*DBG*/DEBUG == DBG_FILTERS ? printf("DBG - B_CATCHED!\n") : 0;
		/*DBG*/DEBUG == DBG_FILTERS ? matched++ : 0;
		if(sel==NULL){
				setNodePointer(pos,curb->item);
				cnt++;
			}else{
				visualMessage(sign_num,step_num,curb->item,sel,cn,ch);
			}
		curb=curb->next;
	}
	freexmlNodeList(lista);
	freexmlNodeList(listb);
	/*DBG*/DEBUG == DBG_FILTERS ? printf("DBG - OR->MATCHED %d\n",matched) : 0;
	return (cnt>0)? pos : freexmlNodeList(pos);
}


#endif
